
#include "../include/buffer.h"
#include "../include/core.h"
#include "../include/fastArray.h"
#include "../include/server.h"
#include "../include/session.h"
#include "../include/mylog.h"

#include "ae.h"
#include "anet.h"
#include "event_msgqueue.h"
#include "zmalloc.h"

#include <stdio.h>

static unsigned long long nextServerId = 0;

static void onAccept(struct aeEventLoop *eventLoop, int fd, void *clientData, int mask) {
	struct server* s = (struct server*) clientData;
	if (!s) {
		return;
	}

    struct core* c = s->core;
    if (!c) {
    	return;
    }

	struct session* session = initSession();
	if (!session) {
		return;
	}
	mylog(LOG_DEBUG, "on accept, session id[%d]", session->id);
	char neterr[256];
	int cfd = anetTcpAccept(neterr, s->fd, session->cip,  &session->cport);
    if (cfd == AE_ERR) {
    	mylog(LOG_WARNING, "in on accept, anetTcpAccept error, session id[%d]!!!", session->id);
    	destroySession(session);
    	session = NULL;
        return;
    }

    anetNonBlock(NULL,  cfd);
    anetTcpNoDelay(NULL, cfd);

    session->cfd = cfd;
    session->callBackHandle = s->serverCallBack;
    session->privateData = s->privateData;

    int ret = dispathWorkThread(c, session);
    if (ret == -1) {
    	mylog(LOG_WARNING, "IN ON ACCEPT!!!");
    	destroySession(session);
    	session = NULL;
    }
}

struct server* initServer(core* c, char *err, int port, char *bindaddr) {
	if (!c) {
		mylog(LOG_WARNING, "zcalloc server error, core is null!!! ");
		return NULL;
	}

	struct server* s = NULL;
	if ( !(s = zcalloc(sizeof(*s)))) {
		mylog(LOG_WARNING, "zcalloc server error!!!");
		return NULL;
	}

	if ( !(s->serverCallBack = zcalloc(sizeof(*(s->serverCallBack)))) ) {
		mylog(LOG_WARNING, "zcalloc server callback error!!!");
		zfree(s);
		return NULL;
	}

	s->core = c;
	s->id = nextServerId;
    s->port = port;
    s->bindaddr = zstrdup(bindaddr);
	s->fd = anetTcpServer(s->neterr, s->port, s->bindaddr);
	if (s->fd == ANET_ERR) {
		mylog(LOG_WARNING, "in initServer anetTcpServer error!!!");
		zfree(s->serverCallBack);
		zfree(s->bindaddr);
		zfree(s);
		return NULL;
	}

    anetNonBlock(NULL,  s->fd);
    anetTcpNoDelay(NULL, s->fd);
	aeCreateFileEvent(s->core->eventLoop, s->fd, AE_READABLE, onAccept, s);
	mylog(LOG_INFO, "init server success, server id[%d], addr[%s], port[%d]!!!", s->id, s->bindaddr, s->port);
	return s;
}

void destroyServer(server* s) {
	if (!s) {
		return;
	}

	mylog(LOG_INFO, "destroy  server, server id[%d], addr[%s], port[%d]!!!", s->id, s->bindaddr, s->port);
	aeDeleteFileEvent(s->core->eventLoop, s->fd, AE_READABLE);
	if (s->fd) {
		close(s->fd);
	}

	if (s->bindaddr) {
		zfree(s->bindaddr);
	}

	if (s->serverCallBack) {
		zfree(s->serverCallBack);
		s->serverCallBack = NULL;
	}

	zfree(s);
	return;
}
